package com.ctrun.view.cateye.indicatorview.widget.banner;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by ctrun on 2017/12/13.
 */

public class LoopViewPager2<T> extends FrameLayout {
    private static final String TAG = LoopViewPager2.class.getSimpleName();
    private static final int DEFAULT_LOOP_TIME = 3000;

    private ViewPager2 mViewPager2;
    private long mLoopTime = DEFAULT_LOOP_TIME;
    private boolean mAutoLoop = true;
    private boolean mCanLoop = true;
    private boolean mLooping;

    private LoopTask mLoopTask;

    public LoopViewPager2(Context context) {
        this(context, null);
    }

    public LoopViewPager2(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LoopViewPager2(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        mLoopTask = new LoopTask(this);

        mViewPager2 = new ViewPager2(context);
        mViewPager2.setId(ViewCompat.generateViewId());

        View childView = mViewPager2.getChildAt(0);
        if (childView instanceof RecyclerView) {
            childView.setOverScrollMode(OVER_SCROLL_NEVER);
        }

        mViewPager2.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

        attachViewToParent(mViewPager2, 0, mViewPager2.getLayoutParams());
    }

    public LoopViewPager2<T> bindLifecycle(Lifecycle lifecycle) {
        lifecycle.addObserver(mLifecycleEventObserver);
        return this;
    }

    public LoopViewPager2<T> setLoopTime(long loopTime) {
        if (loopTime < 1000) {
            loopTime = 1000;
        }
        mLoopTime = loopTime;
        return this;
    }

    public LoopViewPager2<T> setAutoLoop(boolean autoLoop) {
        mAutoLoop = autoLoop;
        return this;
    }

    public LoopViewPager2<T> setCanLoop(boolean canLoop) {
        mCanLoop = canLoop;
        return this;
    }

    private boolean checkCanLoop() {
        return mCanLoop && getAdapter() != null && getAdapter().getRealItemCount() > 1;
    }

    public boolean isLooping() {
        return mLooping;
    }

    /***
     * 开始轮循
     */
    public void startLoop() {
        //如果是正在轮循的话先停掉
        if(mLooping) {
            stopLoop();
        }

        if (!mActive || !mAutoLoop || !mCanLoop) {
            return;
        }

        if (getAdapter() == null || getAdapter().getRealItemCount() <= 1) {
            return;
        }

        mLooping = true;
        postDelayed(mLoopTask, mLoopTime);
    }

    public void stopLoop() {
        mLooping = false;
        removeCallbacks(mLoopTask);
    }

    /**
     *  触碰控件的时候，轮循应该停止，离开的时候如果之前是开启轮循的话则重新启动轮循
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        if (action == MotionEvent.ACTION_UP||action == MotionEvent.ACTION_CANCEL||action == MotionEvent.ACTION_OUTSIDE) {
            // 开始轮循
            if(mCanLoop) {
                startLoop();
            }
        } else if (action == MotionEvent.ACTION_DOWN) {
            // 停止轮循
            if(mCanLoop) {
                stopLoop();
            }
        }

        return super.dispatchTouchEvent(ev);
    }

    public ViewPager2 getViewPager2() {
        return mViewPager2;
    }

    public LoopAdapter<T, ? extends RecyclerView.ViewHolder> getAdapter() {
        //noinspection unchecked
        return (LoopAdapter<T, ? extends RecyclerView.ViewHolder>) mViewPager2.getAdapter();
    }

    @SuppressWarnings("rawtypes")
    public LoopViewPager2 setAdapter(RecyclerView.Adapter adapter) {
        if (!(adapter instanceof LoopAdapter)) {
            throw new IllegalArgumentException("adapter must instanceof LoopAdapter!");
        }

        mViewPager2.setAdapter(adapter);
        return this;
    }

    public void create() {
        create(new ArrayList<>());
    }

    public void create(List<T> data) {
        if (getAdapter() == null) {
            throw new NullPointerException("adapter must be set before create() call");
        }

        getAdapter().setCanLoop(mCanLoop);
        setData(data);
    }

    private boolean mActive = false;
    LifecycleEventObserver mLifecycleEventObserver = (source, event) -> {
        if (event == Lifecycle.Event.ON_RESUME) {
            mActive = true;
            startLoop();
        } else if (event == Lifecycle.Event.ON_PAUSE) {
            mActive = false;
            stopLoop();
        }
    };

    public void setData(List<? extends T> data) {
        if (getAdapter() != null) {
            getAdapter().setData(data, true);

            stopLoop();
            resetCurrentItem();
            startLoop();
        }
    }

    private void resetCurrentItem() {
        if (checkCanLoop()) {
            mViewPager2.setCurrentItem(getAdapter().getRealItemCount()  * 100000, false);
        } else {
            mViewPager2.setCurrentItem(0, false);
        }
    }


    static class LoopTask implements Runnable {

        private final WeakReference<LoopViewPager2<?>> reference;

        LoopTask(LoopViewPager2<?> loopViewPager2) {
            this.reference = new WeakReference<>(loopViewPager2);
        }

        @Override
        public void run() {
            LoopViewPager2<?> loopViewPager2 = reference.get();

            if (loopViewPager2 != null) {
                if (loopViewPager2.mViewPager2 != null && loopViewPager2.mLooping) {
                    int page = loopViewPager2.mViewPager2.getCurrentItem() + 1;
                    loopViewPager2.mViewPager2.setCurrentItem(page, true);

                    loopViewPager2.postDelayed(loopViewPager2.mLoopTask, loopViewPager2.mLoopTime);
                }
            }
        }
    }
}
